package android.system.http;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import Decoder.BASE64Encoder;
import android.os.Handler;
import android.util.Log;

/**
 * http 通讯
 * 
 * @author leiyong
 * 
 */
public class HttpComm {
	private HttpRespond mHttpRespond = null;

	private Map<String, Object> mHttpGetParameters = null;
	private List<NameValuePair> mHttpPostParameters = null;
	private String mHttpStringParameters = null;
	
	private String mURL = null;

	private Thread mThread = null;

	private RespondCode mRespondCode = null;
	private String mRespondString = null;
	private int mHttpStateCode = 0;
	private boolean mHttpConnecting = false;
	
	public static String mHttpSession = null;
	private Handler handler = new Handler();
	private Runnable mRunnable = null;
	private HTTP_TYPE mHttpType = null;
	
	private static final int TIMEOUT_TIME = 40*1000;
	
	// 内部错误码
	private enum RespondCode {
		RECEIVED_SUCCESSFUL,
		HTTP_STATUS_ERROR,
		CLIENT_PROTOCOL_EXCEPTION,
		PARAM_ERROR,
		IO_EXCEPTION,
		EXCEPTION,
	}
	
	public enum HTTP_TYPE{
		GET,
		POST,
		POST_STRING
	}

	// 通知用户原因
	public enum Reasion {
		SERVICE_ERROR,//服务器问题，等服务器恢复再试
		CONNECT_ERROR,//网络连接，查看本地网络配置，若是GPRS则查询服务是否开通
		PARAM_ERROR,//参数错误
		NO_LOGIN,//未登录
		PASSWORD_ERROR,//密码错误
		UNKNOW_ERROR//未知错误
	}
	
	//接口用于回调
	public interface HttpRespond {
		void error(Reasion reasion,String error_detail);
		void received(String rec_string);
	}
	
	//
	//get构造
	public HttpComm(String url, HTTP_TYPE type, Map<String, Object> params, HttpRespond respond) {
		mURL = url;
		mHttpGetParameters = params;
		mHttpRespond = respond;
		mHttpType = type;
		mHttpConnecting = true;
	}
	
	//post构造
	public HttpComm(String url, HTTP_TYPE type, List<NameValuePair> params, HttpRespond respond) {
		mURL = url;
		mHttpPostParameters = params;
		mHttpRespond = respond;
		mHttpType = type;
		mHttpConnecting = true;
	}
	
	//post string构造
	public HttpComm(String url, HTTP_TYPE type, String string, HttpRespond respond) {
		mURL = url;
		mHttpStringParameters = string;
		mHttpRespond = respond;
		mHttpType = type;
		mHttpConnecting = true;
	}
	
	/**
	 * 启动线程
	 * （也可用于重试）
	 */
	public void star() {
		mRunnable = new Runnable() {
			public void run() {
				if (null != mHttpRespond) {
					switch (mRespondCode) {
					case HTTP_STATUS_ERROR:
					case CLIENT_PROTOCOL_EXCEPTION:
						mHttpRespond.error(Reasion.SERVICE_ERROR, mRespondString);// mHttpStateCode
						break;
					case IO_EXCEPTION:
					case EXCEPTION:
						mHttpRespond.error(Reasion.UNKNOW_ERROR, mRespondString);
						break;
					case PARAM_ERROR:
						mHttpRespond.error(Reasion.PARAM_ERROR, mRespondString);
						break;
					case RECEIVED_SUCCESSFUL:
						mHttpRespond.received(mRespondString);
						break;
					}
				}
			}
		};
		
		mThread = new Thread() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				super.run();
				
				HttpClient httpClient = getHttpClient();
				if((mHttpType == HTTP_TYPE.GET) && (null != mHttpGetParameters)){
					doGet(httpClient, mURL, mHttpGetParameters);
				}else if((mHttpType == HTTP_TYPE.POST) && (null != mHttpPostParameters)){
					doPost(httpClient, mURL, mHttpPostParameters);
				}else if((mHttpType == HTTP_TYPE.POST_STRING) && (null != mHttpStringParameters)){
					doPostString(httpClient, mURL, mHttpStringParameters);
				}else{
					//param error!
				}
				
				mHttpConnecting = false;
			}

			@Override
			public synchronized void start() {
				// TODO Auto-generated method stub
				super.start();
			}
		};
		
		mThread.start();
	}
	
	public void Respond(RespondCode respond_code,int http_state_code, String respond_string) {
		mRespondCode = respond_code;
		mRespondString = respond_string;
		mHttpStateCode = http_state_code;
		handler.post(mRunnable);
	}
	
	private HttpClient getHttpClient() {
		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_TIME);// 连接超时
		HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_TIME);// Socket 超时
		HttpConnectionParams.setSocketBufferSize(httpParams, 8192*10);// Socket缓存大小
		
		HttpClientParams.setRedirecting(httpParams, true);// 重定向，缺省为 true
		
		String userAgent = "android newttl";// 设置 user agent
		HttpProtocolParams.setUserAgent(httpParams, userAgent);

		HttpClient httpClient = new DefaultHttpClient(httpParams);
		return httpClient;
	}


	private void doGet(HttpClient httpClient, String url, Map<String, Object> params) {
		String paramStr = "";
		Iterator<?> iter = params.entrySet().iterator();
		int i=0;
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			String key = (String)entry.getKey();
			
			String val = String.valueOf(entry.getValue());
			
			String val_for_url = null;
//			if(key.equals("con")&&val!=null&&!val.trim().equals("")){
//				//val=val.replace(" ", "0x001101");
//				Log.d("HTTP","=======val :" + val );
//				val=encode(val.getBytes());
//				Log.d("HTTP","=======val :" + val );
//				
//			}
			try {
				val_for_url = URLEncoder.encode(val, "UTF-8");
				
				//val_for_url=toUTF8(val);
				//val_for_url = URLEncoder.encode(val_for_url, "UTF-8");// 二次编码，否则会乱码
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				Respond(RespondCode.PARAM_ERROR, 0, "Error:" + e.getMessage().toString());
				return;
			}
//			if(key.equals("con")&&val_for_url!=null&&!val_for_url.trim().equals("")){
//				//val.replace(" ", "0x001101");
//				encode(val_for_url.getBytes());
//				
//			}
			Log.d("HTTP","key "+key+" val :" + val + "   val_for_url :" + val_for_url);
			if(i==0){
				paramStr += paramStr = "?" + key + "=" + val_for_url;
			}else{
				paramStr += paramStr = "&" + key + "=" + val_for_url;
			}
			i++;
		}
		
		if (!paramStr.equals("")) {
			// paramStr = paramStr.replaceFirst("&", "?");
			url += paramStr;
		}
		
		Log.d("HTTP","URL========="+url);
		
	       
		HttpGet httpRequest = new HttpGet(url);
		
		//httpRequest.addHeader("Pragma", "no-cache");
		//httpRequest.addHeader("Cache-Control", "no-cache");
		
		//session 机制
		//尝试请求Cookie，然后只从中截取session段，下次请求时以这个session段作为Cookie。
		if(null != mHttpSession){
			httpRequest.addHeader("Cookie", mHttpSession);
		}
		//Log.d("HTTP", "CCCCCCCCCC  req session=" + session);

		try {
			HttpResponse httpResponse = httpClient.execute(httpRequest);
			
			Header header = httpResponse.getFirstHeader("Set-Cookie");
			if (header != null) {
				String value = header.getValue();
				//Log.d("HTTP", "CCCCCCCCCC  rsp   value=" + value);//JSESSIONID=51C6459F49A1511F6A006D59D2E468F8.jvm8060; Path=/

				mHttpSession = value.substring(0, value.indexOf(";"));
				//Log.d("HTTP", "CCCCCCCCCC  rsp session=" + session);//JSESSIONID=51C6459F49A1511F6A006D59D2E468F8.jvm8060
			}
			
			int StatusCode = httpResponse.getStatusLine().getStatusCode();
			if (StatusCode == 200) {
				String strResult = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
				Respond(RespondCode.RECEIVED_SUCCESSFUL,StatusCode, strResult);
			} else {
				Respond(RespondCode.HTTP_STATUS_ERROR,StatusCode, "Error:"+ httpResponse.getStatusLine().toString());
			}
		} catch (ClientProtocolException e) {
			Respond(RespondCode.CLIENT_PROTOCOL_EXCEPTION,0, "ClientProtocolException");
			//e.printStackTrace();
		} catch (IOException e) {
			Respond(RespondCode.IO_EXCEPTION, 0, "IOException");
			e.printStackTrace();
		} catch (Exception e) {
			Respond(RespondCode.EXCEPTION, 0, "Exception");
			//e.printStackTrace();
		}
	}

	private void doPost(HttpClient httpClient, String url, List<NameValuePair> params) {
		HttpPost httpRequest = new HttpPost(url);

		try {
			httpRequest.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
			HttpResponse httpResponse = httpClient.execute(httpRequest);
			int StatusCode = httpResponse.getStatusLine().getStatusCode();
			if (StatusCode == 200) {
				String strResult = EntityUtils.toString(httpResponse.getEntity());
				Respond(RespondCode.RECEIVED_SUCCESSFUL,StatusCode, strResult);
			} else {
				Respond(RespondCode.HTTP_STATUS_ERROR,StatusCode, "Error:"+ httpResponse.getStatusLine().toString());
			}
		} catch (ClientProtocolException e) {
			Respond(RespondCode.CLIENT_PROTOCOL_EXCEPTION,0, "ClientProtocolException");
			//e.printStackTrace();
		} catch (IOException e) {
			Respond(RespondCode.IO_EXCEPTION,0, "IOException");
			//e.printStackTrace();
		}catch (Exception e) {
			Respond(RespondCode.EXCEPTION,0, "Exception");
			//e.printStackTrace();
		}
	}
	
	private void doPostString(HttpClient httpClient, String url, String string) {
		HttpPost httpRequest = new HttpPost(url);
		try {
			httpRequest.setEntity(new StringEntity(string, HTTP.UTF_8));
			HttpResponse httpResponse = httpClient.execute(httpRequest);
			int StatusCode = httpResponse.getStatusLine().getStatusCode();
			if (StatusCode == 200) {
				String strResult = EntityUtils.toString(httpResponse.getEntity());
				Respond(RespondCode.RECEIVED_SUCCESSFUL,StatusCode, strResult);
			} else {
				Respond(RespondCode.HTTP_STATUS_ERROR,StatusCode, "Error:"+ httpResponse.getStatusLine().toString());
			}
		} catch (ClientProtocolException e) {
			Respond(RespondCode.CLIENT_PROTOCOL_EXCEPTION,0, "ClientProtocolException");
			//e.printStackTrace();
		} catch (IOException e) {
			Respond(RespondCode.IO_EXCEPTION,0, "IOException");
			//e.printStackTrace();
		}catch (Exception e) {
			Respond(RespondCode.EXCEPTION,0, "Exception");
			//e.printStackTrace();
		}
	}
	
	/*protected static synchronized String getUrlContent(String url) throws ApiException {
        if (sUserAgent == null) {
            throw new ApiException("User-Agent string must be prepared");
        }

        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(url);
        request.setHeader("User-Agent", sUserAgent); //设置客户端标识
        try {
            HttpResponse response = client.execute(request);
            StatusLine status = response.getStatusLine();
            if (status.getStatusCode() != HTTP_STATUS_OK) {
                throw new ApiException("Invalid response from server: " +
                        status.toString());
            }
            HttpEntity entity = response.getEntity();
            InputStream inputStream = entity.getContent(); //获取HTTP返回的数据流
            ByteArrayOutputStream content = new ByteArrayOutputStream();
            int readBytes = 0;
            while ((readBytes = inputStream.read(sBuffer)) != -1) {
                content.write(sBuffer, 0, readBytes); //转化为字节数组流
            }
            return new String(content.toByteArray()); //从字节数组构建String
        } catch (IOException e) {
            throw new ApiException("Problem communicating with API", e);
        }
    }*/

	public void stop() {
		//断开接口
		mHttpRespond = null;
		//结束线程
		
	}

	

	
	private String TAG = "Http";
	private boolean print_enable = true;
	private void my_log(String print) {
		if (print_enable) {
			Log.d(TAG, print); 
		}
	}
	
	public boolean getConnecting(){
		return mHttpConnecting;
	}
	 public static String toUTF8(String str)throws UnsupportedEncodingException {  
         String result = str;  
         
             result = changeCharSet(str, "UTF-8");  
       
        return result;  
	 }  
	 private static String changeCharSet(  
	              String str, String newCharset) throws UnsupportedEncodingException {  
	          if (str != null) {  
	              // 用默认字符编码解码字符串。   
	              byte[] bs = str.getBytes();  
	             // 用新的字符编码生成字符串   
	              return new String(bs, newCharset);  
	          }  
	         return str; 
}
	
}
